﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using System.IO;
using System.Threading;

using Lucene.Net.Index;
using Lucene.Net.Store;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Search;
using Lucene.Net.Util;
using Lucene.Net.Analysis.PanGu;

using XMK.Tadong.InnerElement;
using XMK.Utils;
using XMK.Tadong.DataSync.Biz;
using XMK.Framework.DataAccess;
using XMK.Tadong.Model;
using XMK.Framework.ElasticSearch;
using XMK.Framework.Model;


namespace XMK.Tadong.DataSyncService
{
    public class XMKFileLuceneDataUpdater : ITask
    {
        private static string updaterName = "XMKFileLuceneDataUpdater";

        public void Task()
        {
            while (true)
            {
                int rowCount = 1;
                do 
                {
                    DateTime startTime = DateTime.Now;
                    Console.WriteLine("XMKFileLuceneDataUpdater Start");
                    long lastUpdateTime;
                    
                    if (!QueryLastUpdateTime(out lastUpdateTime))
                    {
                        Console.WriteLine("XMKFileLuceneDataUpdater Exception End");
                        break;
                    }
                    DataTable table = QueryLastFileData(lastUpdateTime);
                    if (table == null || table.Rows.Count == 0)
                    {
                        rowCount = 0;
                        Console.WriteLine("XMKFileLuceneDataUpdater End，没有需要扫描的数据！");
                        break;
                    }

                    rowCount = table.Rows.Count;

                    long count = 0;

                    LuceneAccess luceneAccess = new LuceneAccess(DataSyncConfig.XMKFileIndexPath
                        , LuceneAnalyzerType.Standard);
                    IndexWriter deleteWriter = luceneAccess.GetIndexWriter();
                    //先删除
                    foreach (DataRow row in table.Rows)
                    {
                        string deleteFileID = ParseHelper.Parse<string>(row["FILE_ID"]);
                        deleteWriter.DeleteDocuments(LuceneQuery.Eq("FILE_ID", deleteFileID).LuQuery);
                    }
                    deleteWriter.Commit();
                    deleteWriter.Optimize();
                    deleteWriter.Dispose();

                    //再添加
                    IndexWriter addWriter = luceneAccess.GetIndexWriter();
                    foreach (DataRow row in table.Rows)
                    {
                        try
                        {
                            lastUpdateTime = ParseHelper.Parse<long>(row["UPDATE_TIME"]);

                            Document doc = new Document();
                            doc.Add(new Field("FILE_CRT_DATE", ParseHelper.Parse<string>(row["FILE_CRT_DATE"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("KEYW", ParseHelper.Parse<string>(row["KEYW"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("UPD_TIME", ParseHelper.Parse<string>(row["UPD_TIME"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("FILE_TYPE", ParseHelper.Parse<string>(row["FILE_TYPE"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("FILE_ABST", ParseHelper.Parse<string>(row["FILE_ABST"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("USER_ID", ParseHelper.Parse<string>(row["USER_ID"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("FILE_AUTHOR", ParseHelper.Parse<string>(row["FILE_AUTHOR"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("FILE_VERSION", ParseHelper.Parse<string>(row["FILE_VERSION"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("DEST_OBJ", ParseHelper.Parse<string>(row["DEST_OBJ"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("BIZ_OBJ", ParseHelper.Parse<string>(row["BIZ_OBJ"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("SECRET_LVL", ParseHelper.Parse<string>(row["SECRET_LVL"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("LANG_TYPE", ParseHelper.Parse<string>(row["LANG_TYPE"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("TEAM_ID", ParseHelper.Parse<string>(row["TEAM_ID"]), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("TEAM_NAME", ParseHelper.Parse<string>(row["TEAM_NAME"]), Field.Store.YES, Field.Index.NOT_ANALYZED));

                            //元数据
                            doc.Add(new Field("META_DATA", 
                                string.Concat(ParseHelper.Parse<string>(row["FILE_AUTHOR"]), "|"
                                , ParseHelper.Parse<string>(row["DEST_OBJ"]), "|"
                                , ParseHelper.Parse<string>(row["BIZ_OBJ"])), 
                                Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));

                            string fileID = ParseHelper.Parse<string>(row["FILE_ID"]);
                            string savePath = ParseHelper.Parse<string>(row["SAVE_PATH"]);
                            string fileName = ParseHelper.Parse<string>(row["FILE_NAME"]);
                            //string fileExt = ParseHelper.Parse<string>(row["FILE_EXT"]);
                            
                            //文件创建日期
                            NumericField fileCreateDateNumField = new NumericField("FILE_CRT_DATE_NUM", Field.Store.YES, true);
                            DateTime fileCreateDate = ParseHelper.Parse<DateTime>(row["FILE_CRT_DATE"], new DateTime(1990, 1, 1));
                            fileCreateDateNumField.SetLongValue(ParseHelper.Parse<long>(fileCreateDate.ToString("yyyyMMddHHmmss")));
                            doc.Add(fileCreateDateNumField);

                            //下载次数
                            int downAmount = ParseHelper.Parse<int>(row["DOWN_AMOUNT"], 0);
                            NumericField downAmountField = new NumericField("DOWN_AMOUNT", Field.Store.YES, true);
                            downAmountField.SetIntValue(downAmount);
                            doc.Add(downAmountField);

                            string fileCont = string.Empty;

                            //取文件内容
                            if (!string.IsNullOrWhiteSpace(savePath))
                            {
                                if (!savePath.Contains(":"))
                                {
                                    savePath = Path.Combine(DataSyncConfig.RootDirectoryPath, savePath.TrimStart('\\', '/'));
                                }
                                if (!File.Exists(savePath))
                                {
                                    LogHelper.WriteLog(LogType.Info,
                                        string.Format("TB_TEAM_FILE||FILE_ID:{0} 指定的路径{1}不存在！", fileID, savePath));
                                }
                                else
                                {
                                    fileCont = FileHelper.ReadText(savePath);
                                }
                            }

                            doc.Add(new Field("FILE_ID", fileID, Field.Store.YES, Field.Index.NOT_ANALYZED));
                            //doc.Add(new Field("FILE_EXT", fileExt.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                            doc.Add(new Field("FILE_SIZE", ParseHelper.Parse<string>(row["FILE_SIZE"]),
                                Field.Store.YES, Field.Index.NO));

                            //标题
                            doc.Add(new Field("FILE_NAME", fileName, Field.Store.YES,
                                Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));

                            //正文
                            doc.Add(new Field("FILE_CONT", fileCont, Field.Store.YES,
                                Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));

                            addWriter.AddDocument(doc);

                            count++;
                            LogHelper.WriteLog(LogType.Info, string.Format("XMKFileLuceneDataUpdater FILE_ID={0}", fileID));
                        }
                        catch (System.Exception ex)
                        {
                            LogHelper.WriteLog(LogType.Error,
                                string.Format("XMKFileLuceneDataUpdater 索引异常 [FILE_ID={0}] :{1} ", row["FILE_ID"], ex.ToString()));
                        }

                    }

                    addWriter.Commit();
                    addWriter.Optimize();
                    addWriter.Dispose();

                    WriteSyncLog(startTime, lastUpdateTime, count);

                    Console.WriteLine("XMKFileLuceneDataUpdater End");

                } while (rowCount > 0);

                Thread.Sleep(SleepMillSeconds);
            }
            

        }

        private void WriteSyncLog(DateTime startTime, long lastUpdateTime, long count)
        {
            try
            {
                string logSql = string.Format(@"insert into tb_datasync_log(task_name, last_upd_time, start_time, end_time, rcd_count, task_desc)
                                                values(:p_task_name, :p_last_upd_time, :p_start_time, :p_end_time, :p_rcd_count, :p_task_desc)");
                DbCmdHelper cmd = new DbCmdHelper(DataSyncConfig.TadongDbProvider, logSql, delegate
                {
                    return DbCmdHelper.CreateParameters(DataSyncConfig.TadongDbProvider,
                        "task_name", "last_upd_time", "start_time", "end_time", "rcd_count", "task_desc").ToArray();
                });
                cmd.DbCmdInfo.CommandType = CommandType.Text;
                cmd.SetParamValues(updaterName, lastUpdateTime, startTime, DateTime.Now, count, "定时器扫描完成");
                DbManager.ExecNonQuery(cmd);
            }
            catch (System.Exception ex)
            {
                LogHelper.WriteLog(LogType.Error,
                    string.Format("XMKFileLuceneDataUpdater 扫描日志记录异常 :{0} ", ex.ToString()));
            }
        }

        private DataTable QueryLastFileData(long lastUpdateTime)
        {
            try
            {
                DbCmdHelper cmd = new DbCmdHelper(DataSyncConfig.TadongDbProvider, "sp_getnewxmkdata", delegate
                {
                    return DbCmdHelper.CreateParameters(DataSyncConfig.TadongDbProvider, true, "updatetime").ToArray();
                });

                OrderInfo order = new OrderInfo();
                PageInfo pageInfo = new PageInfo();
                pageInfo.PageSize = RowCount;
                pageInfo.CurrentPage = 1;

                cmd.SetParamValues(order, pageInfo, lastUpdateTime);

                cmd.DbCmdInfo.CommandType = CommandType.StoredProcedure;

                return DbManager.ExecutePageDataTable(cmd, pageInfo);
            }
            catch (System.Exception ex)
            {
                LogHelper.WriteLog(LogType.Error,
                        string.Format("XMKFileLuceneDataUpdater 索引异常 || {0} ", ex.ToString()));
            }
            return null;
        }

        private bool QueryLastUpdateTime(out long lastDateTime)
        {
            bool isOK = true;
            lastDateTime = long.Parse(DateTime.Now.ToString("yyyyMMddHHmmssffffff").Substring(0, 18));
            try
            {
                string sql = string.Format(@"select max(a.last_upd_time) upd_time  from tb_datasync_log a
                                                where a.task_name = '{0}' ", updaterName);

                DbCmdHelper cmd = new DbCmdHelper(DataSyncConfig.TadongDbProvider, sql);
                cmd.DbCmdInfo.CommandType = CommandType.Text;
                lastDateTime = ParseHelper.Parse<long>(DbManager.ExecScalar(cmd));
                
            }
            catch (System.Exception ex)
            {
                isOK = false;
                LogHelper.WriteLog(LogType.Error,
                        string.Format("XMKFileLuceneDataUpdater 读取上一次同步时间异常 :{0} ", ex.ToString()));
            }
            return isOK;
            
        }

        public int SleepMillSeconds
        {
            get;
            set;
        }

        public int RowCount
        {
            get;
            set;
        }
    }
}
